﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Drawing;
using System.IO;

using Vitruvian.Serialization;
using Vitruvian.Serialization.Xml;
using Vitruvian.Serialization.Formatters;
using Vitruvian.Windows.Serialization.Formatters;
using Vitruvian.Logging;
using Vitruvian.Testing;

namespace SpotItServerAPI
{
    [ContainsTests("SymbolSubsystem-UnitTests")]
    [OptimisticSerialization]
    public class Symbol : IComparable
    {
        #region Private Data Members
        private static Logger logger = Logger.GetLogger(typeof(Symbol));
        #endregion

        #region Public Properties

        public Guid Id { get; set; }
        public string Label { get; set; }
        public bool IsPrivate { get; set; }
        public Guid Owner { get; set; }

        [ImageFormatter]
        public Image SymbolImage { get; set; }

        [DontSerialize]
        public SymbolSet ContainingSymbolSet = null;

        #endregion
        
        #region Constructors
        public Symbol()
        {
            Initialize(null, null, false, null);
        }

        public Symbol(SymbolSet containingSybmolSet)
        {
            Initialize(null, null, false, containingSybmolSet);
        }

        public Symbol(string label, Image symbolImage, bool isPrivate)
        {
            Initialize(label, symbolImage, isPrivate, null);
        }

        public Symbol(string label, Image symbolImage, bool isPrivate, SymbolSet containingSymbolSet)
        {
            Initialize(label, symbolImage, isPrivate, containingSymbolSet);
        }

        public Symbol(Symbol origSymbol)
        {
            Initialize(origSymbol.Label, origSymbol.SymbolImage, origSymbol.IsPrivate, null);
        }

        public Symbol(Symbol origSymbol, SymbolSet containingSymbolSet)
        {
            Initialize(origSymbol.Label, origSymbol.SymbolImage, origSymbol.IsPrivate, containingSymbolSet);
        }

        #endregion

        #region Method for IComparable Interface
        public int CompareTo(object obj)
        {
            int result = 1;
            if (obj != null && obj.GetType() == typeof(Symbol))
            {
                Symbol other = obj as Symbol;
                result = this.Id.CompareTo(other.Id);
            }
            return result;
        }

        public override bool Equals(object obj)
        {
            return (CompareTo(obj)==0);
        }

        public override int GetHashCode()
        {
            return base.GetHashCode();
        }

        #endregion

        #region Private Methods
        private void Initialize(string label, Image myImage, bool isPrivate, SymbolSet containingSymbolSet)
        {
            logger.DebugFormat("Initialize a new symbol {0}, private={1}", label, isPrivate);
            Id = Guid.NewGuid();
            Label = (!string.IsNullOrEmpty(label)) ? label : "Unnamed Symbol";
            IsPrivate = isPrivate;
            SymbolImage = myImage;
            ContainingSymbolSet = containingSymbolSet;
        }
        #endregion

        #region Unit Test Cases
#if (DEBUG)
        [SetupTest]
        private void Test_Setup()
        {
        }

        [Test(1)]
        private void Test_Symbol_Constructors_Initialize_and_Properties()
        {
            SymbolSet ss1 = new SymbolSet("Test Set A", false);
            SymbolSet ss2 = new SymbolSet("Test Set B", false);

            Symbol s1 = new Symbol();
            Assert.IsNotEqual(Guid.Empty, s1.Id);
            Assert.IsEqual("Unnamed Symbol", s1.Label);
            Assert.IsNull(s1.SymbolImage);
            Assert.IsFalse(s1.IsPrivate);
            Assert.IsNull(s1.ContainingSymbolSet);

            Bitmap testImage = new Bitmap("../../../Symbols/Alligator.jpg");
            s1 = new Symbol("Alligator", testImage, true, ss1);
            Assert.IsNotEqual(Guid.Empty, s1.Id);
            Assert.IsEqual("Alligator", s1.Label);
            Assert.IsNotNull(s1.SymbolImage);
            Assert.IsEqual(testImage, s1.SymbolImage);
            Assert.IsTrue(s1.IsPrivate);
            Assert.IsEqual(ss1, s1.ContainingSymbolSet);

            Symbol s2 = new Symbol(s1,ss2);
            Assert.IsNotEqual(Guid.Empty, s2.Id);
            Assert.IsNotEqual(s1.Id, s2.Id);
            Assert.IsEqual("Alligator", s2.Label);
            Assert.IsNotNull(s2.SymbolImage);
            Assert.IsEqual(testImage, s2.SymbolImage);
            Assert.IsTrue(s2.IsPrivate);
            Assert.IsEqual(ss2, s2.ContainingSymbolSet);
        }

        [Test(2)]
        private void Test_Compare()
        {
            SymbolSet ss1 = new SymbolSet();
            SymbolSet ss2 = new SymbolSet();
            Bitmap testImage = new Bitmap("../../../Symbols/Alligator.jpg");

            // Create a symbol from the image
            Symbol s1 = new Symbol("Test Symbol 1", testImage, true, ss1);
            Assert.IsNotEqual(Guid.Empty, s1.Id);
            Assert.IsEqual("Test Symbol 1", s1.Label);
            Assert.IsNotNull(s1.SymbolImage);
            Assert.IsEqual(testImage, s1.SymbolImage);
            Assert.IsTrue(s1.IsPrivate);
            Assert.IsEqual(ss1, s1.ContainingSymbolSet);

            Assert.IsEqual(0, s1.CompareTo(s1));

            Symbol s2 = new Symbol(s1, ss2);
            Assert.IsNotEqual(0, s1.CompareTo(s2));

            s2.Id = s1.Id;
            Assert.IsEqual(0, s1.CompareTo(s2));

            Assert.IsTrue(s1.Equals(s2));
        }
#endif
        #endregion

    }
}
